package com.movie.ticket.sale.assembly.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.movie.ticket.sale.assembly.common.MovieTicket;
import com.movie.ticket.sale.assembly.common.Resolver;
import com.movie.ticket.sale.assembly.config.UpdateUtil;
import com.movie.ticket.sale.assembly.entity.*;
import com.movie.ticket.sale.assembly.mapper.ComplainMapper;
import com.movie.ticket.sale.assembly.mapper.OrderTicketMapper;
import com.movie.ticket.sale.assembly.mapper.UserMapper;
import com.movie.ticket.sale.assembly.service.OrderMovieService;
import com.movie.ticket.sale.assembly.service.UserService;
import com.movie.ticket.sale.assembly.service.VipService;
import com.movie.ticket.sale.feignCients.userFeign;
import com.movie.ticket.sale.moviecommon.common.Result;
import com.movie.ticket.sale.pram.*;


import com.sun.org.apache.bcel.internal.generic.NEW;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;


/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author muzi
 * @since 2020-12-07
 */
@RestController
@Slf4j
public class UserController implements userFeign {
    @Autowired
    private UserService userService;
    @Autowired
    private OrderMovieService orderMovieService;
    @Autowired
    private ComplainMapper complainMapper;
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MovieTicket movieTicket;

    @Autowired
    private UpdateUtil updateUtil;
    @Autowired
    private OrderTicketMapper orderTicketMapper;
    @Autowired
    private VipService vipService;

    @Autowired
    private RedissonClient redissonClient;


    /**
     * 作者:木子
     * 方法：获取用户信息
     * 参数： 传入保存的对象
     * 返回值: user
     */

    public Result getOne() {
        String tel = Resolver.getTel();
        log.info("token中的tel:{}", tel);
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("tel", tel);
        //查询
        User one = userService.getOne(wrapper);
        return Result.success(one);
    }

    /**
     * 作者:木子
     * 方法：修改用户信息 动态修改 除了头像之外
     * 参数： user
     * 返回值: result
     */

    public Result changeUser(UserPram userPram) {
        String tel = Resolver.getTel();
        userPram.setTel(tel);
        int num = userService.changeUser(userPram);
        if (num == 0) {
            return Result.fail(403, "修改失败,密码少于6位");
        }
        return Result.success("修改成功");
    }

    /**
     * 作者:木子
     * 方法：修改用户头像
     * 参数： user
     * 返回值: result
     */

    public Result changeUserHead(@RequestParam("path") MultipartFile path) {
        String tel = Resolver.getTel();
        Integer id = Resolver.getId();
        //修改
        User user1 = userMapper.selectById(1);
        Result user = updateUtil.updateOneFile("user", path, id);//添加到服务器
        //获取地址
        String url = (String) user.getData();
        user1.setHeadPhoto(url);
        userService.updateById(user1);

        return Result.success("修改头像地址为："+url);
    }

    /**
     * 作者:木子
     * 方法：查询自己往期评论
     * 参数： user
     * 返回值: pages
     */
    public Result getComments() {
        //查询评论 封装成一个参数类 返回集合到前端
        String tel = Resolver.getTel();
        List<CommentPram> commentPrams = userService.findCommentPrams(tel);
        return Result.success(commentPrams);
    }

    /**
     * 作者:木子
     * 方法：删除自己的一条评论
     * 参数：
     * 返回值:
     */
    public Result deleteComment(@RequestParam("commentId") int commentId) {

        log.info("传入的评论ID:{}", commentId);
        userService.deleteComment(commentId);
        return Result.success("删除评论成功");
    }

    /**
     * 作者:木子
     * 方法：查询自己所有的订单
     * 参数： 订单id
     * 返回值: 状态
     */

    public Result getUserOrders(@RequestParam(defaultValue = "1") int currPage, @RequestParam(defaultValue = "5") int number) {
        //查询订单 封装成一个参数类 返回集合到前端
        //获取用户的tel ======================================

        Integer userId = Resolver.getId();
        System.out.println("============================================"+userId);
        IPage<OrderPram> userOrders = userService.getUserOrders(currPage, number, userId);

        return Result.success(userOrders);
    }

    /**
     * 作者:木子
     * 方法：查询订单状态的方法
     * 参数： 订单id
     * 返回值: 状态
     */

    public Result getOrderState(@RequestParam("orderId") int orderId) {
        OrderMovie orderMovie = orderMovieService.getById(orderId);
        Integer state = orderMovie.getState();
        if (state == 1) {
            return Result.success("待进行");
        } else if (state == 2) {
            return Result.success("部分退票");
        } else if (state == -2) {
            return Result.success("全部退票");
        } else if (state == 5) {
            return Result.success("全部改签");
        } else if (state == 6) {
            return Result.success("已取票");
        } else if (state == 7) {
            return Result.success("已完成");
        } else if (state == 0) {
            return Result.success("未支付");
        }
        return Result.fail(500, "系统错误");
    }

    /**
     * 作者:木子
     * 方法：该订单下电影票详情
     * 参数： 订单Id
     * 返回值: 电影票详情
     */

    public Result getTickets(@RequestParam("orderId") int orderId) {
        List<?> tickets = userService.findTickets(orderId);
        return Result.success(tickets);
    }


    /**
     * 作者:木子
     * 方法：改签
     * 参数：需要改签的订单号 改签后的座位号组
     * 返回值:
     */
    public Result changeSeat(@RequestParam("orderId") int orderId, @RequestParam("seats") String[] seats, @RequestParam("peridId") Integer peridId) {
        //加锁
        //遍历数组
        RLock rLock = null;
        for(int index = 0;index<seats.length;index++ ){
            rLock = redissonClient.getLock(peridId+seats[index]);
        }

        boolean locked = rLock.tryLock();//对改椅子组加锁成功
        log.info("加锁成功？{}", locked);
        //调用
        int count = userService.changeSeat(orderId, seats, peridId);
        if (count == 0) {
            rLock.unlock();
            log.info("解锁完成");
            return Result.fail(405, "只能改签一次");
        } else if (count == 1) {
            rLock.unlock();
            log.info("解锁完成");
            return Result.fail(406, "进行过退票操作，不能改签");
        } else if (count == 2) {
            rLock.unlock();
            log.info("解锁完成");
            return Result.fail(407, "电影开始2小时内，不能改签");
        }
        log.info("准备解锁{}", locked);
        rLock.unlock();
        log.info("解锁完成");
        return Result.success("改签成功");


    }

    /**
     * 作者:木子
     * 方法：退款
     * 参数：user
     * 返回值: void
     */

    public Result refund(@RequestParam("ticketIds") int[] ticketIds) {
        OrderTicket orderTicket = orderTicketMapper.selectById(ticketIds[0]);
        Integer orderMovieId = orderTicket.getOrderMovieId();
        //通过订单id查询 订单 如果改过票 那么前端不会显示退票按钮了
        OrderMovie orderMovie = orderMovieService.getById(orderMovieId);
        //判断是否只有这 一张票
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("order_movie_id", orderMovieId);
        List<OrderTicket> list = orderTicketMapper.selectList(wrapper);
        Double realPrice = orderMovie.getRealPrice();
        double money = Math.round(realPrice / list.size() * ticketIds.length * 100) / 100.0;
        String tradeNuo = orderMovie.getTradeNuo();
        System.out.println("+++++++++++"+money);
        System.out.println("+++++++++++"+tradeNuo);

        Result refund = movieTicket.refund(tradeNuo, money);
        if (refund.isSuccess()) {
            userService.refund(ticketIds);
            return Result.success("退款已到账");
        }

        return Result.fail(500, "访问过多，退款失败");
    }

    /**
     * 作者:木子
     * 方法：新增评论
     * 参数：orderId user内部获取
     * 返回值:
     */

    public Result addComment(@RequestParam("orderId") int orderId, @RequestParam("comment") String comment, MultipartFile[] paths, Double degree) {

        Integer userId = Resolver.getId();
        System.out.println(userId);
        userService.addComment(userId, orderId, comment, paths, degree);

        return Result.success("评论成功");
    }

    /**
     * 作者:木子
     * 方法：查询所有优惠券 userId为0的优惠券
     * 参数：
     * 返回值: 活动列表
     */

    public Result getAllDiscounts(@RequestParam(defaultValue = "1") int currPage, @RequestParam(defaultValue = "5") int number) {
        IPage<Discount> allDiscounts = userService.getAllDiscounts(currPage, number);
        return Result.success(allDiscounts);
    }

    /**
     * 作者:木子
     * 方法：参加积分兑换优惠券
     * 参数：优惠券的ID user
     * 返回值:void
     */

    public Result changeDiscount(@RequestParam("discountId") int discountId) {
        RLock rLock = redissonClient.getLock(""+discountId);//对该优惠券加锁
        boolean locked = rLock.tryLock();
        log.info("加锁成功？{}",locked);

        Integer userId = Resolver.getId();
        //调用
        int count = userService.changeDiscount(discountId, userId);
        if (count == 0) {
            rLock.unlock();
            return Result.fail(407, "已被兑换");
        } else if (count == 1) {
            rLock.unlock();
            return Result.fail(408, "积分不足，请再接再励");
        }
        rLock.unlock();
        return Result.success("成功兑换");
    }

    /**
     * 作者:木子
     * 方法：查询自己已经兑换的优惠券 按时间过期时间大的排序
     * 参数： user
     * 返回值: discount
     */

    public Result getDiscount(@RequestParam(defaultValue = "1") int currPage, @RequestParam(defaultValue = "5") int number) {
        Integer userId = Resolver.getId();
        IPage<Discount> discounts = userService.getDiscount(currPage, number, userId);
        return Result.success(discounts);
    }

    /**
     * 作者:木子
     * 方法：查询自己的vip 可能多家影院
     * 参数：user
     * 返回值: vipList
     */

    public Result getVip(@RequestParam(defaultValue = "1") int currPage, @RequestParam(defaultValue = "5") int number) {
        Integer userId = Resolver.getId();
        List<?> vip = userService.getVip(currPage, number, userId);
        return Result.success(vip);
    }
    public Result getVips(@RequestParam(defaultValue = "1") int currPage, @RequestParam(defaultValue = "5") int number){
        Page<Vip> page = new Page<>(currPage,number);
        IPage<Vip> vips = userMapper.findVips(page);

        return Result.success(vips);
    }


    /**
     * 作者:木子
     * 方法：购买该影院的vip
     * 参数： cinemaId user
     * 返回值:
     */
    public Result buyVip(@RequestParam("vipId") int vipId, @RequestParam("mouth") int mouth) {
        //办理会员 建立绑定
        //支付成功 返回信息
        //通过vipId查询vip
        int userId = Resolver.getId();
        String tel = Resolver.getTel();
        //生成订单号
        String tradeNuo = "TOrderVip_" + userId + "_" + System.currentTimeMillis()+"_"+tel;
        Vip vip = vipService.getById(vipId);
        Integer priceVar = vip.getPriceVar();
        double price = (15 - priceVar * Math.log10(mouth)) * mouth;



        Result result = movieTicket.aliPay("注册会员", tradeNuo, "购买会员", price);
        if (!result.isSuccess()) {
            //支付失败 直接返回
            return Result.fail(405, "服务繁忙，支付失败，请再次支付");
        }
        userService.buyVip(price, tradeNuo, mouth, userId, vipId);

        return Result.success("办理成功，订单号："+tradeNuo);
    }

    /**
     * 作者:木子
     * 方法：查询所有拥有vip服务的影院
     * 参数：
     * 返回值: cinemaList
     */

    public Result getCinemaVip(@RequestParam(defaultValue = "1") int currPage, @RequestParam(defaultValue = "5") int number) {
        IPage<CinemaVip> cinemaVips = userService.getCinemaVip(currPage, number);
        return Result.success(cinemaVips);
    }

    /**
     * 作者:木子
     * 方法：登录
     * 参数：手机号 密码
     * 返回值:void
     */

    public Result login(@RequestParam("tel") String tel, @RequestParam("password") String password) {
        //登录===========联合网关 和  redis  ===================================

        User user = userMapper.selectById(1);

        return Result.success(user);
    }

    /**
     * 作者:木子
     * 方法：注册
     * 参数： 手机号 密码 验证码
     * 返回值: void
     */

    public Result register(@RequestParam("tel") String tel, @RequestParam("password") String password, @RequestParam("code") String code) {
        //注册===========联合网关 和  redis  ===================================

        return Result.success();
    }

    /**
     * 作者:木子
     * 方法：查看自己投诉影院的记录
     * 参数： user
     * 返回值:
     */

    public Result getComplaint(@RequestParam(defaultValue = "1") int currPage, @RequestParam(defaultValue = "5") int number) {
        Integer userId = Resolver.getId();
        Page page = new Page(currPage, number);
        IPage<ComplainPram> userComplains = userMapper.findUserComplain(page, userId);
        return Result.success(userComplains);
    }

    /**
     * 作者:木子
     * 方法：删除对某影院的投诉
     * 参数： complaintId
     * 返回值:
     */

    public Result deleteComplaint(@RequestParam("id") int id) {
        complainMapper.deleteById(id);
        return Result.success("删除成功");
    }

    /**
     * 作者:木子
     * 方法：新增对电影院的投诉
     * 参数： orderId
     * 返回值:
     */

    public Result addComplaint(@RequestParam("orderId") int orderId, @RequestParam("complaint") String content) {
        Integer userId = Resolver.getId();
        userService.addComplain(orderId, content, userId);
        return Result.success("投诉成功");
    }

    /**
    *作者:木子
    *方法：加锁测试
    *参数： 随便传的
    *返回值:
    */
    public Result addSuo(@RequestParam("test") int[] test){
        RLock rLock = null;

        for(int index = 0;index<test.length;index++ ){
            rLock= redissonClient.getLock(""+test[index]);
            System.out.println(rLock);
        }
        boolean locked = rLock.tryLock();//对改椅子组加锁成功
        System.out.println(rLock);

            rLock.unlock();


        return Result.success();
    }

}

